package com.atguigu.gmall.activity.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.mapper.SeckillOrderMapper;
import com.atguigu.gmall.activity.pojo.SeckillOrder;
import com.atguigu.gmall.activity.pojo.UserRecode;
import com.atguigu.gmall.activity.service.SeckillService;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.activity.SeckillGoods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author luYinLei
 * @version 1.0
 * @date 2021/7/15 10:01
 */
@Service
public class SeckillServiceImpl implements SeckillService {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 秒杀商品列表
     *
     * @param time
     * @return
     */
    @Override
    public List<SeckillGoods> getSeckillGoods(String time) {
        List<SeckillGoods> seckillGoods = redisTemplate.boundHashOps("SeckillGoods_" + time).values();
        return seckillGoods;
    }

    /**
     * 秒杀商品详情列表
     *
     * @param time
     *  @param id
     * @return
     */
    @Override
    public SeckillGoods getSeckillGoodsDetails(String time ,String id) {
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);
        return seckillGoods;
    }

    @Autowired
    private RabbitService rabbitService;
    /**
     * 排队下单
     *
     * @param time
     * @param skuId
     * @param userId
     * @return
     */
    @Override
    public UserRecode addUserRecode(String time, String skuId, String userId) {
        //记录用户排队信息
        UserRecode userRecode = new UserRecode();
        //防止用户重复下单
        Long increment = redisTemplate.boundValueOps("SeckillUserQueue_" + userId).increment( 1);
        //判断
        if (increment>1){
            userRecode.setStatus(3);
            userRecode.setMsg("重复排队！");
            return userRecode;
        }
        //状态排队中
        userRecode.setStatus(1);
        //补充数据
        userRecode.setUsername(userId);
        userRecode.setCreateTime(new Date());
        userRecode.setGoodsId(skuId);
        userRecode.setNum(1);
        //存入redis
        redisTemplate.boundValueOps("SeckillStatus_" + userId).set(userRecode);
        //发送消息异步下单
        rabbitService.sendMessage(
                "seckill_exchange",
                "seckill.order.add",
                JSONObject.toJSONString(userRecode));
        return userRecode;
    }

    /**
     * 查询用户排队信息
     *
     * @param userId
     * @return
     */
    @Override
    public UserRecode getUserRecode(String userId) {
        return (UserRecode) redisTemplate.boundValueOps("SeckillStatus_"+userId).get();
    }

    /**
     * 查询秒杀订单信息
     *
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    public List<SeckillOrder> getSeckillOrderList(String userId, String orderId) {
        if (StringUtils.isEmpty(orderId)) {
            //查询所有订单信息
            return redisTemplate.boundHashOps("SeckillOrder_" + userId).values();
        } else {
            List<SeckillOrder> seckillOrders = new ArrayList<>();
            //查询指定订单信息
            SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder_" + userId).get(orderId);
            seckillOrders.add(seckillOrder);
            return seckillOrders;
        }
    }

    @Autowired
    private SeckillOrderMapper seckillOrderMapper;

    /**
     * 支付成功
     *
     * @param map
     */
    @Override
    public void paySuccess(Map<String, String> map) {
        //获取微信支付的附加参数
        String attach = map.get("attach");
        //判断附加参数是否为空
        if (StringUtils.isEmpty(attach)) {
            //获取支付宝附加参数
            attach = map.get("passback_params");
        }
        //转换类型
        Map<String, String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = attachMap.get("out_trade_no");
        //从redis中获取用户订单信息
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate
                                            .boundHashOps("SeckillOrder_" + username)
                                            .get(outTradeNo);
        //判断前置状态
        if (seckillOrder==null &&seckillOrder.getStatus().equals("0")){
            //修改订单状态
            seckillOrder.setStatus("1");
            seckillOrder.setPayTime(new Date());
            //获取微信支付单号
            String transactionId = map.get("transaction_id");
            if (StringUtils.isEmpty(transactionId)){
                transactionId= map.get("trade_no");
            }
            seckillOrder.setOutTradeNo(transactionId);
            //修改redis数据
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo, seckillOrder);
            //将订单数据存入数据库
            seckillOrderMapper.insert(seckillOrder);
            //删除排队标识
            redisTemplate.delete("SeckillUserQueue_"+username);
            //删除排队状态
            redisTemplate.delete("seckillStatus_"+username);
        }

    }

    /**
     * 支付失败
     *
     * @param map
     */
    @Override
    public void payFail(Map<String, String> map) {
        //获取微信支付的附加参数
        String attach = map.get("attach");
        //判断附加参数是否为空
        if (StringUtils.isEmpty(attach)) {
            //获取支付宝附加参数
            attach = map.get("passback_params");
        }
        //转换类型
        Map<String, String> attachMap = JSONObject.parseObject(attach, Map.class);
        String username = attachMap.get("username");
        String outTradeNo = attachMap.get("out_trade_no");
        //从redis中获取用户订单信息
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate
                .boundHashOps("SeckillOrder_" + username)
                .get(outTradeNo);
        //判断前置状态
        if (seckillOrder == null && seckillOrder.getStatus().equals("0")) {
            //修改订单状态信息
            seckillOrder.setStatus("2");
            //修改redis订单
            redisTemplate.boundHashOps("SeckillOrder_" + username).put(outTradeNo, seckillOrder);
            //保存到数据库
            seckillOrderMapper.insert(seckillOrder);
            //回滚数据库与redis库存
            UserRecode userRecode = (UserRecode) redisTemplate.boundValueOps("SeckillStatus_" + username).get();
            rollBackSeckillGoodsNum(userRecode.getTime(), userRecode.getGoodsId(), userRecode.getNum());
            //删除排队标识
            redisTemplate.delete("SeckillUserQueue_" + username);
            //删除排队状态
            redisTemplate.delete("SeckillStatus_"+username);
        }
    }

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    /**
     * 回滚秒杀商品的库存
     * @param time
     * @param goodsId
     * @param num
     */
    private void rollBackSeckillGoodsNum(String time, String goodsId, Integer num) {
        //从redis获取商品数据
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(goodsId);
        //判断
        if (seckillGoods==null){
            //更新数据库库存数据
            seckillGoodsMapper.updateSeckillGoodsStock(goodsId,num);
        }else {
            //构建库存长度的数组
            String[] seckillGoodsQueue = getSeckillGoodsQueue(goodsId, num);
            redisTemplate.boundListOps("seckillGoodsQueue_"+goodsId).rightPushAll(seckillGoodsQueue);
            //回滚库存数据
            redisTemplate.boundHashOps("SeckillGoodsStockNum").increment(goodsId,num);
        }
    }

    /**
     * 构建库存长度的数组
     * @param skuId
     * @param stockCount
     * @return
     */
    private String[] getSeckillGoodsQueue(String skuId, Integer stockCount) {
        //构建库存长度的数组
        String[] ids = new String[stockCount];
        for (int i = 0; i <stockCount ; i++) {
            ids[i] = skuId;
        }
        return ids;
    }

}
